import { Router } from '@angular/router';
import { Component, OnInit, Input } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { NzModalService } from 'ng-zorro-antd/modal';
import { NzMessageService } from 'ng-zorro-antd/message';
import { ConfigStateService, LocalizationService } from '@abp/ng.core';
import { EditState } from 'joy-abpui-angular';
import { map } from 'rxjs/operators';
import { UniqueCodeSettingService } from '../../core/unique-code-setting/unique-code-setting.service';
import { CustomerDto, CustomerService } from '../../proxy/joy/erp/basic-archives/customers';
import { CustomerTypeDto, CustomerTypeService } from '../../proxy/joy/erp/basic-archives/customers';
import { OperatorDto, OperatorService } from '../../proxy/joy/erp/basic-archives/staff';
import { OperatorRefSelectService } from '../../staff/operator-ref-select/operator-ref-select.services';
import { debounce } from '../../core/debounce.util';

@Component({
  selector: 'lib-customer-daw-entity',
  templateUrl: './customer-daw-entity.component.html',
  styleUrls: ['./customer-daw-entity.component.less'],
})
export class CustomerDawEntityComponent implements OnInit {
  entityConfig = {
    defaultValue: {
      enabled: true
    },
  };

  @Input() id?: string;

  editState: EditState;
  validateForm: FormGroup;
  currentEntity: CustomerDto;
  customerTypeTreeData: any[] = [];

  get codeInputDisabled() {
    var uniqueCodeConfigration = this.config.getSetting("UniqueCodeConfigration:Joy.Erp.BasicArchives.Customers.Customer");
    var uniqueCodeConfigrationObj = JSON.parse(uniqueCodeConfigration);
    return uniqueCodeConfigrationObj["AutoCode"];
  }

  isSaveBtnDisabled = () => {
    return this.editState == EditState.Empty || this.editState == EditState.View || !this.validateForm.valid
  }

  showOperatorSelect = (selectedOperator: OperatorDto) => {
    var modalRef = this.operatorRefSelectService.show(selectedOperator ? [selectedOperator] : [], { multiple: false });

    return modalRef.afterClose.pipe(
      map(selectedOperators => {
        if (selectedOperators && selectedOperators.length > 0) {
          return selectedOperators[0];
        }
        return null;
      })
    );
  }

  getOperatorDetail = (operatorId: string) => {
    return this.operatorService.get(operatorId);
  }

  constructor(
    public router: Router,
    public fb: FormBuilder,
    public config: ConfigStateService,
    public message: NzMessageService,
    public modal: NzModalService,
    public modalService: NzModalService,
    public localizationService: LocalizationService,
    public entityService: CustomerService,
    public customerTypeService: CustomerTypeService,
    public operatorService: OperatorService,
    public uniqueCodeSettingService: UniqueCodeSettingService,
    public operatorRefSelectService: OperatorRefSelectService,
  ) {}

  ngOnInit(): void {
    this.editState = EditState.Empty;
    this.currentEntity = this.entityConfig.defaultValue as CustomerDto;
    this.validateForm = this.fb.group({
      code: [this.entityConfig.defaultValue['code']],
      name: [this.entityConfig.defaultValue['name'], [Validators.required, Validators.maxLength(200)]],
      shortName: [this.entityConfig.defaultValue['shortName'], [Validators.maxLength(100)]],
      customerTypeId: [this.entityConfig.defaultValue['customerTypeId'], [Validators.required]],
      contact: [this.entityConfig.defaultValue['contact'], [Validators.maxLength(100)]],
      phone: [this.entityConfig.defaultValue['phone'], [Validators.maxLength(50)]],
      address: [this.entityConfig.defaultValue['address'], [Validators.maxLength(500)]],
      operatorId: [this.entityConfig.defaultValue['operatorId']],
      enabled: [this.entityConfig.defaultValue['enabled']],
    });

    this.updateCodeValidators();
    this.loadCustomerType();

    if (this.id) {
      this.entityService.get(this.id).subscribe(entity => {
        if (entity) {
          this.setCurrentEntity(entity);
        }
      });
    }

    this.validateForm.valueChanges.subscribe(_ => {
      if (this.editState == EditState.Empty) {
        this.editState = EditState.Creating;
      } else if (this.editState == EditState.View) {
        this.editState = EditState.Editing;
      }
    });
  }

  @debounce()
  save() {
    if (this.editState == EditState.Creating) {
      this.entityService
        .create({ ...this.validateForm.value })
        .subscribe(entity => {
          if (!!entity) {
            this.setCurrentEntity(entity);
            this.message.success(this.l('BasicArchives::UI:Message.AddSuccess'));
          }
        });
    } else if (this.editState == EditState.Editing) {
      this.entityService
        .update(this.currentEntity.id, {
          ...this.currentEntity,
          ...this.validateForm.value
        })
        .subscribe(entity => {
          if (!!entity) {
            this.setCurrentEntity(entity);
            this.message.success(this.l('BasicArchives::UI:Message.EditSuccess'));
          }
        });
    }
  }

  @debounce()
  giveup() {
    this.giveUpConfirm().then(_ => {
      if (this.editState == EditState.Creating) {
        //表单状态为创建时，清空数据
        this.changeToEmpty();
      } else if (this.editState == EditState.Editing) {
        //表单状态为编辑时，恢复原数据
        this.setCurrentEntity(this.currentEntity);
      }
    });
  }

  @debounce()
  new() {
    this.checkDirty().then(_ => this.changeToEmpty());
  }

  @debounce()
  copy() {
    this.checkDirty().then(_ => {
      this.setCurrentEntity({...this.currentEntity, code: ""});
      this.currentEntity = this.entityConfig.defaultValue as CustomerDto;
      this.editState = EditState.Creating;
    });
  }

  @debounce()
  delete() {
    this.modal.confirm({
      nzTitle: this.l('BasicArchives::UI:Confirm.Title.Tips'),
      nzContent: this.l('BasicArchives::UI:Confirm.Content.DeleteConfirm'),
      nzOkText: this.l('BasicArchives::UI:Confirm.Button.OK'),
      nzCancelText: this.l('BasicArchives::UI:Confirm.Button.Cancel'),
      nzOnOk: () => {
        this.entityService.delete(this.currentEntity.id).subscribe(_ => this.changeToEmpty());
      },
    });
  }

  @debounce()
  refresh() {
    if(this.currentEntity.id) {
      this.entityService.get(this.currentEntity.id).subscribe(entity => {
        if (!!entity) {
          this.setCurrentEntity(entity);
        }
      });
    } else {      
      this.changeToEmpty();
    }
  }

  @debounce()
  search(code) {
    if(code) {
      this.entityService.find(code).subscribe(entity => {
        if (!!entity) {
          this.setCurrentEntity(entity);
        } else {
          this.message.warning(this.l('BasicArchives::UI:Message.CanNotFund', this.l('BasicArchives::Menu:BasicArchives.ArchivesManagement.Customers.Customer'), code));
        }
      });
    }
  }

  @debounce()
  uniqueCodeSetting() {
    this.uniqueCodeSettingService.show('UniqueCodeConfigration:Joy.Erp.BasicArchives.Customers.Customer').afterClose.subscribe(_ => {
      this.updateCodeValidators();
    });
  }

  getErrorMessage(fieldName: string): string {
    return this.getControlErrorMessage(this.validateForm, fieldName);
  }

  getControlErrorMessage(formGroup: any, fieldName: string): string {
    const control = formGroup.get(fieldName);
    if (control && control.invalid && control.touched) {
      if (control.hasError('required')) {
        return this.l('BasicArchives::UI:Validation:Required');
      }
      if (control.hasError('maxlength')) {
        return this.l('BasicArchives::UI:Validation:MaxLength', control.getError('maxlength').requiredLength);
      }
    }
    return '';
  }

  protected loadCustomerType() {
    this.customerTypeService.getChildren(null, true).subscribe(result => {
      this.customerTypeTreeData = this.convertToTreeSelectData(result.items);
    });
  }

  protected convertToTreeSelectData(items: CustomerTypeDto[]): any[] {
    return this.createEntityTreeNodes(items, null);
  }

  protected createEntityTreeNodes(
    list: CustomerTypeDto[],
    parent: CustomerTypeDto,
    parentIdPropretyName?: string,
    idPropertyName?: string
  ): any[] {
    let treeNodes: any[] = [];
    let parentIdKey = !parentIdPropretyName ? 'parentId' : parentIdPropretyName;
    let idKey = !idPropertyName ? 'id' : idPropertyName;
    let parentId = !parent ? null : parent[idKey];
    for (let node of list.filter(x => x[parentIdKey] == parentId)) {
      const children = this.createEntityTreeNodes(list, node, parentIdKey, idKey);

      treeNodes = [
        ...treeNodes,
        {
          title: node.displayName,
          value: node.id,
          key: node.id,
          children
        },
      ];
    }
    return treeNodes;
  }

  protected changeToEmpty() {
    this.validateForm.reset(this.entityConfig.defaultValue, { emitEvent: false });
    this.refreshFormValidationStatus();
    this.editState = EditState.Empty;
  }

  protected setCurrentEntity(entity: CustomerDto) {
    this.currentEntity = entity;
    this.validateForm.reset(this.currentEntity, { emitEvent: false });
    this.refreshFormValidationStatus();
    this.editState = EditState.View;
  }

  protected giveUpConfirm(): Promise<any> {
    return new Promise((resolve, reject) => {
      if (this.editState != EditState.Creating && this.editState != EditState.Editing)
        return reject();
      this.modal.confirm({
        nzTitle: this.l('BasicArchives::UI:Confirm.Title.Tips'),
        nzContent: this.l('BasicArchives::UI:Confirm.Content.GiveUpConfirm'),
        nzOkText: this.l('BasicArchives::UI:Confirm.Button.OK'),
        nzCancelText: this.l('BasicArchives::UI:Confirm.Button.Cancel'),
        nzOnOk: () => resolve(null),
      });
    });
  }

  protected checkDirty(): Promise<any> {
    return new Promise(resolve => {
      if (this.editState == EditState.Creating || this.editState == EditState.Editing) {
        this.modal.confirm({
          nzTitle: this.l('BasicArchives::UI:Confirm.Title.Tips'),
          nzContent: this.l('BasicArchives::UI:Confirm.Content.ChangeStateConfirm'),
          nzOkText: this.l('BasicArchives::UI:Confirm.Button.OK'),
          nzCancelText: this.l('BasicArchives::UI:Confirm.Button.Cancel'),
          nzOnOk: () => resolve(null),
        });
      } else {
        resolve(null);
      }
    });
  }

  protected l(key: string, ...args: any[]): string {
    return this.localizationService.instant(key, ...args);
  }

  protected refreshFormValidationStatus() {
    Object.keys(this.validateForm.controls).forEach(key => {
      this.validateForm.controls[key].markAsPristine();
      this.validateForm.controls[key].updateValueAndValidity();
    });
  }

  protected updateCodeValidators() {
    const codeControl = this.validateForm.get('code');
    const validators = [Validators.maxLength(200)];
    if (!this.codeInputDisabled) {
      validators.push(Validators.required);
    }
    codeControl.setValidators(validators);
    codeControl.updateValueAndValidity();
  }
} 